home *** CD-ROM | disk | FTP | other *** search
/ Ultra Pack / UltraComputing Partner Applications.iso / SunLabs / tclTK / src / tk4.0 / tkImgFmtGIF.c < prev    next >
C/C++ Source or Header  |  1995-06-15  |  17KB  |  695 lines

  1. /*
  2.  * tkImgFmtGIF.c --
  3.  *
  4.  * A photo image file handler for GIF files. Reads 87a and 89a GIF files.
  5.  * At present there is no write function.
  6.  *
  7.  * Derived from the giftoppm code found in the pbmplus package 
  8.  * and tkImgFmtPPM.c in the tk4.0b2 distribution by -
  9.  *
  10.  * Reed Wade (wade@cs.utk.edu), University of Tennessee
  11.  *
  12.  * Copyright (c) 1995 Sun Microsystems, Inc.
  13.  *
  14.  * See the file "license.terms" for information on usage and redistribution
  15.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  16.  *
  17.  * This file also contains code from the giftoppm program, which is
  18.  * copyrighted as follows:
  19.  *
  20.  * +-------------------------------------------------------------------+
  21.  * | Copyright 1990, David Koblas.                                     |
  22.  * |   Permission to use, copy, modify, and distribute this software   |
  23.  * |   and its documentation for any purpose and without fee is hereby |
  24.  * |   granted, provided that the above copyright notice appear in all |
  25.  * |   copies and that both that copyright notice and this permission  |
  26.  * |   notice appear in supporting documentation.  This software is    |
  27.  * |   provided "as is" without express or implied warranty.           |
  28.  * +-------------------------------------------------------------------+
  29.  */
  30.  
  31. static char sccsid[] = "@(#) tkImgFmtGIF.c 1.3 95/06/14 22:49:02";
  32.  
  33. #include "tkInt.h"
  34. #include "tkPort.h"
  35.  
  36. /*
  37.  * The format record for the GIF file format:
  38.  */
  39.  
  40. static int      FileMatchGIF _ANSI_ARGS_((FILE *f, char *fileName,
  41.             char *formatString, int *widthPtr, int *heightPtr));
  42. static int      FileReadGIF  _ANSI_ARGS_((Tcl_Interp *interp,
  43.             FILE *f, char *fileName, char *formatString,
  44.             Tk_PhotoHandle imageHandle, int destX, int destY,
  45.             int width, int height, int srcX, int srcY));
  46.  
  47. Tk_PhotoImageFormat tkImgFmtGIF = {
  48.     "GIF",            /* name */
  49.     FileMatchGIF,   /* fileMatchProc */
  50.     NULL,           /* stringMatchProc */
  51.     FileReadGIF,    /* fileReadProc */
  52.     NULL,           /* stringReadProc */
  53.     NULL,           /* fileWriteProc */
  54.     NULL,           /* stringWriteProc */
  55. };
  56.  
  57. #define INTERLACE        0x40
  58. #define LOCALCOLORMAP        0x80
  59. #define BitSet(byte, bit)    (((byte) & (bit)) == (bit))
  60. #define MAXCOLORMAPSIZE        256
  61. #define CM_RED            0
  62. #define CM_GREEN        1
  63. #define CM_BLUE            2
  64. #define MAX_LWZ_BITS        12
  65. #define LM_to_uint(a,b)         (((b)<<8)|(a))
  66. #define ReadOK(file,buffer,len)    (fread(buffer, len, 1, file) != 0)
  67.  
  68. /*
  69.  * Prototypes for local procedures defined in this file:
  70.  */
  71.  
  72. static int        DoExtension _ANSI_ARGS_((FILE *fd, int label,
  73.                 int *transparent));
  74. static int        GetCode _ANSI_ARGS_((FILE *fd, int code_size,
  75.                 int flag));
  76. static int        GetDataBlock _ANSI_ARGS_((FILE *fd,
  77.                 unsigned char *buf));
  78. static int        LWZReadByte _ANSI_ARGS_((FILE *fd, int flag,
  79.                 int input_code_size));
  80. static int        ReadColorMap _ANSI_ARGS_((FILE *fd, int number,
  81.                 unsigned char buffer[3][MAXCOLORMAPSIZE]));
  82. static int        ReadGIFHeader _ANSI_ARGS_((FILE *f, int *widthPtr,
  83.                 int *heightPtr));
  84. static int        ReadImage _ANSI_ARGS_((Tcl_Interp *interp,
  85.                 char *imagePtr, FILE *fd, int len, int height,
  86.                 unsigned char cmap[3][MAXCOLORMAPSIZE],
  87.                 int interlace, int transparent));
  88.  
  89. /*
  90.  *----------------------------------------------------------------------
  91.  *
  92.  * FileMatchGIF --
  93.  *
  94.  *  This procedure is invoked by the photo image type to see if
  95.  *  a file contains image data in GIF format.
  96.  *
  97.  * Results:
  98.  *  The return value is 1 if the first characters in file f look
  99.  *  like GIF data, and 0 otherwise.
  100.  *
  101.  * Side effects:
  102.  *  The access position in f may change.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106.  
  107. static int
  108. FileMatchGIF(f, fileName, formatString, widthPtr, heightPtr)
  109.     FILE *f;            /* The image file, open for reading. */
  110.     char *fileName;        /* The name of the image file. */
  111.     char *formatString;        /* User-specified format string, or NULL. */
  112.     int *widthPtr, *heightPtr;    /* The dimensions of the image are
  113.                  * returned here if the file is a valid
  114.                  * raw GIF file. */
  115. {
  116.     return ReadGIFHeader(f, widthPtr, heightPtr);
  117. }
  118.  
  119. /*
  120.  *----------------------------------------------------------------------
  121.  *
  122.  * FileReadGIF --
  123.  *
  124.  *    This procedure is called by the photo image type to read
  125.  *    GIF format data from a file and write it into a given
  126.  *    photo image.
  127.  *
  128.  * Results:
  129.  *    A standard TCL completion code.  If TCL_ERROR is returned
  130.  *    then an error message is left in interp->result.
  131.  *
  132.  * Side effects:
  133.  *    The access position in file f is changed, and new data is
  134.  *    added to the image given by imageHandle.
  135.  *
  136.  *----------------------------------------------------------------------
  137.  */
  138.  
  139. static int
  140. FileReadGIF(interp, f, fileName, formatString, imageHandle, destX, destY,
  141.     width, height, srcX, srcY)
  142.     Tcl_Interp *interp;        /* Interpreter to use for reporting errors. */
  143.     FILE *f;            /* The image file, open for reading. */
  144.     char *fileName;        /* The name of the image file. */
  145.     char *formatString;        /* User-specified format string, or NULL. */
  146.     Tk_PhotoHandle imageHandle;    /* The photo image to write into. */
  147.     int destX, destY;        /* Coordinates of top-left pixel in
  148.                  * photo image to be written to. */
  149.     int width, height;        /* Dimensions of block of photo image to
  150.                  * be written to. */
  151.     int srcX, srcY;        /* Coordinates of top-left pixel to be used
  152.                  * in image being read. */
  153. {
  154.     int fileWidth, fileHeight;
  155.     int nBytes;
  156.     Tk_PhotoImageBlock block;
  157.     unsigned char buf[100];
  158.     int bitPixel;
  159.     unsigned int colorResolution;
  160.     unsigned int background;
  161.     unsigned int aspectRatio;
  162.     unsigned char localColorMap[3][MAXCOLORMAPSIZE];
  163.     unsigned char colorMap[3][MAXCOLORMAPSIZE];
  164.     int useGlobalColormap;
  165.     int transparent = -1;
  166.  
  167.     if (!ReadGIFHeader(f, &fileWidth, &fileHeight)) {
  168.     Tcl_AppendResult(interp, "couldn't read GIF header from file \"",
  169.         fileName, "\"", NULL);
  170.     return TCL_ERROR;
  171.     }
  172.     if ((fileWidth <= 0) || (fileHeight <= 0)) {
  173.     Tcl_AppendResult(interp, "GIF image file \"", fileName,
  174.         "\" has dimension(s) <= 0", (char *) NULL);
  175.     return TCL_ERROR;
  176.     }
  177.  
  178.     if (fread(buf, 1, 3, f) != 3) {
  179.     return TCL_OK;
  180.     }
  181.     bitPixel = 2<<(buf[0]&0x07);
  182.     colorResolution = (((buf[0]&0x70)>>3)+1);
  183.     background = buf[1];
  184.     aspectRatio = buf[2];
  185.  
  186.     if (BitSet(buf[0], LOCALCOLORMAP)) {    /* Global Colormap */
  187.     if (!ReadColorMap(f, bitPixel, colorMap)) {
  188.         Tcl_AppendResult(interp, "error reading color map",
  189.             (char *) NULL);
  190.         return TCL_ERROR;
  191.     }
  192.     }
  193.  
  194.     if ((srcX + width) > fileWidth) {
  195.     width = fileWidth - srcX;
  196.     }
  197.     if ((srcY + height) > fileHeight) {
  198.     height = fileHeight - srcY;
  199.     }
  200.     if ((width <= 0) || (height <= 0)
  201.         || (srcX >= fileWidth) || (srcY >= fileHeight)) {
  202.     return TCL_OK;
  203.     }
  204.  
  205.     Tk_PhotoExpand(imageHandle, destX + width, destY + height);
  206.  
  207.     block.width = fileWidth;
  208.     block.height = fileHeight;
  209.     block.pixelSize = 3;
  210.     block.pitch = 3 * fileWidth;
  211.     block.offset[0] = 0;
  212.     block.offset[1] = 1;
  213.     block.offset[2] = 2;
  214.     nBytes = fileHeight * block.pitch;
  215.     block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
  216.  
  217.     while (1) {
  218.     if (fread(buf, 1, 1, f) != 1) {
  219.         /*
  220.          * Premature end of image.  We should really notify
  221.          * the user, but for now just show garbage.
  222.          */
  223.  
  224.         break;
  225.     }
  226.  
  227.     if (buf[0] == ';') {
  228.         /*
  229.          * GIF terminator.
  230.          */
  231.  
  232.         break;
  233.     }
  234.  
  235.     if (buf[0] == '!') {
  236.         /*
  237.          * This is a GIF extension.
  238.          */
  239.  
  240.         if (fread(buf, 1, 1, f) != 1) {
  241.         interp->result =
  242.             "error reading extension function code in GIF image";
  243.         goto error;
  244.         }
  245.         if (DoExtension(f, buf[0], &transparent) < 0) {
  246.         interp->result = "error reading extension in GIF image";
  247.         goto error;
  248.         }
  249.         continue;
  250.     }
  251.  
  252.     if (buf[0] != ',') {
  253.         /*
  254.          * Not a valid start character; ignore it.
  255.          */
  256.         continue;
  257.     }
  258.  
  259.     if (fread(buf, 1, 9, f) != 9) {
  260.         interp->result = "couldn't read left/top/width/height in GIF image";
  261.         goto error;
  262.     }
  263.  
  264.     useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
  265.  
  266.     bitPixel = 1<<((buf[8]&0x07)+1);
  267.  
  268.     if (!useGlobalColormap) {
  269.         if (!ReadColorMap(f, bitPixel, localColorMap)) {
  270.             Tcl_AppendResult(interp, "error reading color map", 
  271.                 (char *) NULL);
  272.             goto error;
  273.         }
  274.         if (ReadImage(interp, (char *) block.pixelPtr, f, fileWidth,
  275.             fileHeight, localColorMap, BitSet(buf[8], INTERLACE),
  276.             transparent) != TCL_OK) {
  277.         goto error;
  278.         }
  279.     } else {
  280.         if (ReadImage(interp, (char *) block.pixelPtr, f, fileWidth,
  281.             fileHeight, colorMap, BitSet(buf[8], INTERLACE),
  282.             transparent) != TCL_OK) {
  283.         goto error;
  284.         }
  285.     }
  286.  
  287.     }
  288.  
  289.     Tk_PhotoPutBlock(imageHandle, &block, destX, destY, fileWidth, fileHeight);
  290.     ckfree((char *) block.pixelPtr);
  291.     return TCL_OK;
  292.  
  293.     error:
  294.     ckfree((char *) block.pixelPtr);
  295.     return TCL_ERROR;
  296.  
  297. }
  298.  
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * ReadGIFHeader --
  303.  *
  304.  *    This procedure reads the GIF header from the beginning of a
  305.  *    GIF file and returns the dimensions of the image.
  306.  *
  307.  * Results:
  308.  *    The return value is 1 if file "f" appears to start with
  309.  *    a valid GIF header, 0 otherwise.  If the header is valid,
  310.  *    then *widthPtr and *heightPtr are modified to hold the
  311.  *    dimensions of the image.
  312.  *
  313.  * Side effects:
  314.  *    The access position in f advances.
  315.  *
  316.  *----------------------------------------------------------------------
  317.  */
  318.  
  319. static int
  320. ReadGIFHeader(f, widthPtr, heightPtr)
  321.     FILE *f;            /* Image file to read the header from */
  322.     int *widthPtr, *heightPtr;    /* The dimensions of the image are
  323.                  * returned here. */
  324. {
  325.     unsigned char buf[7];
  326.  
  327.     if ((fread(buf, 1, 6, f) != 6)
  328.         || ((strncmp("GIF87a", (char *) buf, 6) != 0)
  329.         && (strncmp("GIF89a", (char *) buf, 6) != 0))) {
  330.     return 0;
  331.     }
  332.  
  333.     if (fread(buf, 1, 4, f) != 4) {
  334.     return 0;
  335.     }
  336.  
  337.     *widthPtr = LM_to_uint(buf[0],buf[1]);
  338.     *heightPtr = LM_to_uint(buf[2],buf[3]);
  339.     return 1;
  340. }
  341.  
  342. /*
  343.  *-----------------------------------------------------------------
  344.  * The code below is copied from the giftoppm program and modified
  345.  * just slightly.
  346.  *-----------------------------------------------------------------
  347.  */
  348.  
  349. static int
  350. ReadColorMap(fd,number,buffer)
  351. FILE        *fd;
  352. int     number;
  353. unsigned char   buffer[3][MAXCOLORMAPSIZE];
  354. {
  355.     int     i;
  356.     unsigned char   rgb[3];
  357.  
  358.     for (i = 0; i < number; ++i) {
  359.         if (! ReadOK(fd, rgb, sizeof(rgb)))
  360.             return 0;
  361.  
  362.         buffer[CM_RED][i] = rgb[0] ;
  363.         buffer[CM_GREEN][i] = rgb[1] ;
  364.         buffer[CM_BLUE][i] = rgb[2] ;
  365.     }
  366.     return 1;
  367. }
  368.  
  369.  
  370.  
  371. static int
  372. DoExtension(fd, label, transparent)
  373. FILE    *fd;
  374. int label;
  375. int    *transparent;
  376. {
  377.     static unsigned char buf[256];
  378.     int count = 0;
  379.  
  380.     switch (label) {
  381.         case 0x01:      /* Plain Text Extension */
  382.             break;
  383.  
  384.         case 0xff:      /* Application Extension */
  385.             break;
  386.  
  387.         case 0xfe:      /* Comment Extension */
  388.             do {
  389.                 count = GetDataBlock(fd, (unsigned char*) buf);
  390.             } while (count > 0);
  391.             return count;
  392.  
  393.         case 0xf9:      /* Graphic Control Extension */
  394.             count = GetDataBlock(fd, (unsigned char*) buf);
  395.             if (count < 0) {
  396.                 return 1;
  397.             }
  398.             if ((buf[0] & 0x1) != 0) {
  399.                 *transparent = buf[3];
  400.             }
  401.  
  402.             do {
  403.                 count = GetDataBlock(fd, (unsigned char*) buf);
  404.             } while (count > 0);
  405.             return count;
  406.     }
  407.  
  408.     do {
  409.         count = GetDataBlock(fd, (unsigned char*) buf);
  410.     } while (count > 0);
  411.     return count;
  412. }
  413.  
  414. static int ZeroDataBlock = 0;
  415.  
  416. static int
  417. GetDataBlock(fd, buf)
  418. FILE        *fd;
  419. unsigned char   *buf;
  420. {
  421.     unsigned char   count;
  422.  
  423.     if (! ReadOK(fd,&count,1)) {
  424.         return -1;
  425.     }
  426.  
  427.     ZeroDataBlock = count == 0;
  428.  
  429.     if ((count != 0) && (! ReadOK(fd, buf, count))) {
  430.         return -1;
  431.     }
  432.  
  433.     return count;
  434. }
  435.  
  436.  
  437. static int
  438. ReadImage(interp, imagePtr, fd, len, height, cmap, interlace, transparent)
  439. Tcl_Interp *interp;
  440. char     *imagePtr;
  441. FILE    *fd;
  442. int len, height;
  443. unsigned char   cmap[3][MAXCOLORMAPSIZE];
  444. int interlace;
  445. int transparent;
  446. {
  447.     unsigned char   c;
  448.     int     v;
  449.     int     xpos = 0, ypos = 0, pass = 0;
  450.     char     *colStr;
  451.  
  452.  
  453.     /*
  454.      *  Initialize the Compression routines
  455.      */
  456.     if (! ReadOK(fd,&c,1))  {
  457.         Tcl_AppendResult(interp, "error reading GIF image: ",
  458.             Tcl_PosixError(interp), (char *) NULL);
  459.         return TCL_ERROR;
  460.     }
  461.  
  462.     if (LWZReadByte(fd, 1, c) < 0) {
  463.         interp->result = "format error in GIF image";
  464.         return TCL_ERROR;
  465.     }
  466.  
  467.     if (transparent!=-1 && 
  468.         (colStr = Tcl_GetVar(interp, "TRANSPARENT_GIF_COLOR", 0L))) {
  469.         XColor *colorPtr;
  470.         colorPtr = Tk_GetColor(interp, Tk_MainWindow(interp), 
  471.                               Tk_GetUid(colStr));
  472.         if (colorPtr) {
  473. /*
  474.             printf("color is %d %d %d\n", 
  475.                     colorPtr->red >> 8, 
  476.                     colorPtr->green >> 8, 
  477.                     colorPtr->blue >> 8);
  478. */
  479.             cmap[CM_RED][transparent] = colorPtr->red >> 8;
  480.             cmap[CM_GREEN][transparent] = colorPtr->green >> 8;
  481.             cmap[CM_BLUE][transparent] = colorPtr->blue >> 8;
  482.             Tk_FreeColor(colorPtr);
  483.         }
  484.     }
  485.  
  486.     while ((v = LWZReadByte(fd,0,c)) >= 0 ) {
  487.  
  488.         imagePtr[ (xpos*3)  +  (ypos *len*3)] = cmap[CM_RED][v];
  489.         imagePtr[ (xpos*3)  +  (ypos *len*3) +1] = cmap[CM_GREEN][v];
  490.         imagePtr[ (xpos*3)  +  (ypos *len*3) +2] = cmap[CM_BLUE][v];
  491.  
  492.         ++xpos;
  493.         if (xpos == len) {
  494.             xpos = 0;
  495.             if (interlace) {
  496.                 switch (pass) {
  497.                     case 0:
  498.                     case 1:
  499.                         ypos += 8; break;
  500.                     case 2:
  501.                         ypos += 4; break;
  502.                     case 3:
  503.                         ypos += 2; break;
  504.                 }
  505.  
  506.                 if (ypos >= height) {
  507.                     ++pass;
  508.                     switch (pass) {
  509.                         case 1:
  510.                             ypos = 4; break;
  511.                         case 2:
  512.                             ypos = 2; break;
  513.                         case 3:
  514.                             ypos = 1; break;
  515.                         default:
  516.                             return TCL_OK;
  517.                     }
  518.                 }
  519.             } else {
  520.                 ++ypos;
  521.             }
  522.         }
  523.         if (ypos >= height)
  524.             break;
  525.     }
  526.     return TCL_OK;
  527. }
  528.  
  529. static int
  530. LWZReadByte(fd, flag, input_code_size)
  531. FILE    *fd;
  532. int flag;
  533. int input_code_size;
  534. {
  535.     static int  fresh = 0;
  536.     int     code, incode;
  537.     static int  code_size, set_code_size;
  538.     static int  max_code, max_code_size;
  539.     static int  firstcode, oldcode;
  540.     static int  clear_code, end_code;
  541.     static int  table[2][(1<< MAX_LWZ_BITS)];
  542.     static int  stack[(1<<(MAX_LWZ_BITS))*2], *sp;
  543.     register int    i;
  544.  
  545.  
  546.     if (flag) {
  547.  
  548.         set_code_size = input_code_size;
  549.         code_size = set_code_size+1;
  550.         clear_code = 1 << set_code_size ;
  551.         end_code = clear_code + 1;
  552.         max_code_size = 2*clear_code;
  553.         max_code = clear_code+2;
  554.  
  555.         GetCode(fd, 0, 1);
  556.  
  557.         fresh = 1;
  558.  
  559.         for (i = 0; i < clear_code; ++i) {
  560.             table[0][i] = 0;
  561.             table[1][i] = i;
  562.         }
  563.         for (; i < (1<<MAX_LWZ_BITS); ++i) {
  564.             table[0][i] = table[1][0] = 0;
  565.         }
  566.  
  567.         sp = stack;
  568.  
  569.         return 0;
  570.  
  571.     } else if (fresh) {
  572.  
  573.         fresh = 0;
  574.         do {
  575.             firstcode = oldcode = GetCode(fd, code_size, 0);
  576.         } while (firstcode == clear_code);
  577.         return firstcode;
  578.     }
  579.  
  580.     if (sp > stack)
  581.         return *--sp;
  582.  
  583.     while ((code = GetCode(fd, code_size, 0)) >= 0) {
  584.         if (code == clear_code) {
  585.             for (i = 0; i < clear_code; ++i) {
  586.                 table[0][i] = 0;
  587.                 table[1][i] = i;
  588.             }
  589.  
  590.             for (; i < (1<<MAX_LWZ_BITS); ++i) {
  591.                 table[0][i] = table[1][i] = 0;
  592.             }
  593.  
  594.             code_size = set_code_size+1;
  595.             max_code_size = 2*clear_code;
  596.             max_code = clear_code+2;
  597.             sp = stack;
  598.             firstcode = oldcode = GetCode(fd, code_size, 0);
  599.             return firstcode;
  600.  
  601.     } else if (code == end_code) {
  602.         int     count;
  603.         unsigned char   buf[260];
  604.  
  605.         if (ZeroDataBlock)
  606.             return -2;
  607.  
  608.         while ((count = GetDataBlock(fd, buf)) > 0)
  609.             ;
  610.  
  611.         if (count != 0)
  612.             return -2;
  613.     }
  614.  
  615.     incode = code;
  616.  
  617.     if (code >= max_code) {
  618.         *sp++ = firstcode;
  619.         code = oldcode;
  620.     }
  621.  
  622.     while (code >= clear_code) {
  623.         *sp++ = table[1][code];
  624.         if (code == table[0][code])
  625.             printf("circular table entry BIG ERROR\n");
  626.         code = table[0][code];
  627.     }
  628.  
  629.     *sp++ = firstcode = table[1][code];
  630.  
  631.     if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
  632.  
  633.         table[0][code] = oldcode;
  634.         table[1][code] = firstcode;
  635.         ++max_code;
  636.         if ((max_code>=max_code_size) && (max_code_size < (1<<MAX_LWZ_BITS))) {
  637.             max_code_size *= 2;
  638.             ++code_size;
  639.         }
  640.     }
  641.  
  642.     oldcode = incode;
  643.  
  644.     if (sp > stack)
  645.         return *--sp;
  646.     }
  647.     return code;
  648. }
  649.  
  650.  
  651. static int
  652. GetCode(fd, code_size, flag)
  653. FILE    *fd;
  654. int code_size;
  655. int flag;
  656. {
  657.     static unsigned char    buf[280];
  658.     static int      curbit, lastbit, done, last_byte;
  659.     int         i, j, ret;
  660.     unsigned char       count;
  661.  
  662.     if (flag) {
  663.         curbit = 0;
  664.         lastbit = 0;
  665.         done = 0;
  666.         return 0;
  667.     }
  668.  
  669.  
  670.     if ( (curbit+code_size) >= lastbit) {
  671.         if (done) {
  672.             /* ran off the end of my bits */
  673.             return -1;
  674.         }
  675.         buf[0] = buf[last_byte-2];
  676.         buf[1] = buf[last_byte-1];
  677.  
  678.         if ((count = GetDataBlock(fd, &buf[2])) == 0)
  679.             done = 1;
  680.  
  681.         last_byte = 2 + count;
  682.         curbit = (curbit - lastbit) + 16;
  683.         lastbit = (2+count)*8 ;
  684.     }
  685.  
  686.     ret = 0;
  687.     for (i = curbit, j = 0; j < code_size; ++i, ++j)
  688.         ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
  689.  
  690.  
  691.     curbit += code_size;
  692.  
  693.     return ret;
  694. }
  695.